package com.jiazhong.example.project.bookstore.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiazhong.example.project.bookstore.backend.service.UserService;
import com.jiazhong.example.project.bookstore.commons.bean.Power;
import com.jiazhong.example.project.bookstore.commons.bean.Role;
import com.jiazhong.example.project.bookstore.commons.bean.User;
import com.jiazhong.example.project.bookstore.commons.config.JwtConfig;
import com.jiazhong.example.project.bookstore.commons.handler.*;
import com.jiazhong.example.project.bookstore.commons.mapper.PowerMapper;
import com.jiazhong.example.project.bookstore.commons.mapper.UserMapper;
import com.jiazhong.example.project.bookstore.commons.util.JsonResult;
import com.jiazhong.example.project.bookstore.commons.util.MD5Util;
import com.jiazhong.example.project.bookstore.commons.util.ResultTool;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private PowerMapper powerMapper;
    @Resource
    private HttpServletRequest request;

    @Override
    public JsonResult find(int page) {
        IPage<User> iPage = new Page<>(page, 10);
        List<User> list = list(iPage);
        iPage.setRecords(list);
        return ResultTool.success(iPage);
    }

    @Override
    public JsonResult saveUser(User user) {
        // 密码加密
        String encryptMD5Password = MD5Util.encryptMD5(user.getPassword());
        user.setPassword(encryptMD5Password);
        boolean b = save(user);
        if (!b) {
            throw new UserSaveException("添加用户失败");
        }
        return ResultTool.success("success");
    }

    @Override
    public JsonResult changeStatus(String id, Integer status) {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("status", status);
        boolean b = update(updateWrapper);
        if (!b) {
            throw new UserUpdateException((status == 0 ? "禁用" : "启用") + "用户失败");
        }
        return ResultTool.success("success");
    }

    @Override
    public JsonResult findUserById(String id) {
        User user = getById(id);
        if (user == null) {
            throw new UserNotFoundException("没有找到这个用户");
        }
        return ResultTool.success(user);
    }

    @Override
    public JsonResult updateUser(User user) {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", user.getId());
        updateWrapper.set("username", user.getUsername());
        updateWrapper.set("address", user.getAddress());
        updateWrapper.set("email", user.getEmail());
        updateWrapper.set("phone", user.getPhone());
        boolean b = update(updateWrapper);
        if (!b) {
            throw new UserUpdateException("修改用户失败");
        }
        return ResultTool.success("success");
    }

    /*@Override
    public JsonResult login(String username, String password) {
        // 1. 查询账号是否存在
        User user = loadUsername(username);
        // 2. 检查密码是否正确
        String sqlPassword = user.getPassword();
        String inputPassword = MD5Util.encryptMD5(password);
        if (!sqlPassword.equals(inputPassword)) {
            throw new PasswordFailException("你的密码输入错误");
        }
        // 3. 获取到用户的所有权限（不是登陆成功与否的条件）
        List<Power> powers = getPowers(user.getId());
        user.setPowers(powers);
        // 4. 归类，为了前端查询准备的
        List<Role> roles = getRoles(powers);
        user.setRoles(roles);
        // 5. 将用户的登录信息予以保存（目前是存到了session,后期会放到redis）
        request.getSession().setAttribute("BACKEND_LOGIN_USER", user);
        // 6. 将用户信息返回给前端
        return ResultTool.success(user);
    }*/

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public JsonResult login(String username, String password) {
        // 1. 查询账号是否存在
        User user = loadUsername(username);
        // 2. 检查密码是否正确
        String sqlPassword = user.getPassword();
        String inputPassword = MD5Util.encryptMD5(password);
        if (!sqlPassword.equals(inputPassword)) {
            throw new PasswordFailException("你的密码输入错误");
        }
        // 3. 获取到用户的所有权限（不是登陆成功与否的条件）
        List<Power> powers = getPowers(user.getId());
        user.setPowers(powers);
        // 4. 归类，为了前端查询准备的
        List<Role> roles = getRoles(powers);
        user.setRoles(roles);
        // 5. 将用户的登录信息予以保存 redis
        ValueOperations<String, String> forValue = stringRedisTemplate.opsForValue();
        String token = JwtConfig.getJwtToken(user);
        forValue.set("token:" + user.getId(), token, 1, TimeUnit.DAYS);
        // 6. 将用户信息返回给前端
        return ResultTool.success(token);
    }

    /*@Override
    public JsonResult isLogin(String id) {
        Object obj = request.getSession().getAttribute("BACKEND_LOGIN_USER");
        if (obj == null) {
            return ResultTool.fail(500, "用户没有登陆");
        }
        User user = (User) obj;
        if (!user.getId().equals(id)) {
            return ResultTool.fail(500, "用户没有登陆");
        }
        return ResultTool.success(user);
    }*/

    @Override
    public JsonResult isLogin(String token) {
        boolean b = JwtConfig.checkToken(token);
        if (!b) {
            return ResultTool.fail(500, "用户没有登陆");
        }
        Claims claims = JwtConfig.parseJWT(token);
        Object id = claims.get("id");
        ValueOperations<String, String> forValue = stringRedisTemplate.opsForValue();
        String redisToken = forValue.get("token:" + id);
        if (!Objects.equals(redisToken, token)) {
            return ResultTool.fail(500, "用户没有登陆");
        }
        List<Power> powers = getPowers(id.toString());
        return ResultTool.success(powers);
    }

    // 仅判断账号是否存在
    private User loadUsername(String username) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        queryWrapper.eq("status", 1);
        User user = getOne(queryWrapper);
        if (user == null) {
            throw new UsernameNotFoundException("账号不存在");
        }
        return user;
    }

    private List<Power> getPowers(String id) {
        return powerMapper.findPowerByUserId(id);
    }

    private List<Role> getRoles(List<Power> powers) {
        // 这个是大容器，里边包含了很多的小容器
        List<Role> roles = new ArrayList<>();
        for (Power power : powers) {
            if (power.getStatus() == 0) {
                continue;
            }
            // 拿到我的分类名
            String typeName = power.getTypeName();
            boolean flag = false;
            for (Role role : roles) {
                if (typeName.equals(role.getName())) {
                    role.getPowers().add(power);
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                Role role = new Role();
                role.setName(typeName);
                List<Power> powerList = new ArrayList<>();
                powerList.add(power);
                role.setPowers(powerList);
                roles.add(role);
            }
        }
        return roles;
    }
}
